// Copyright (c) 2007-2008 Simon Fell
//
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE.
//

#import "Folder.h"
#import "File.h"
#import "Pool.h"
#import "Preferences.h"
#import "zkSforceClient.h"
#import "zkQueryResult.h"
#import "zkSObject.h"
#import "zkSoapException.h"

@implementation Folder

- (id)initWithName:(NSString *)nm id:(NSString *)id modstamp:(NSDate *)ms created:(NSDate *)created clientPool:(Pool *)p {
	self = [super initWithName:nm id:id modstamp:ms created:created];
	NSMutableDictionary *atts = [NSMutableDictionary dictionary];
	[atts setObject:NSFileTypeDirectory forKey:NSFileType];
	[atts setObject:[NSNumber numberWithInt:0700] forKey:NSFilePosixPermissions];
	[atts setObject:systemModstamp forKey:NSFileModificationDate];
	[atts setObject:createdDate forKey:NSFileCreationDate];
	attributes = [atts retain];
	clients = [p retain];
	return self;
}

- (void)dealloc {
	[files release];
	[clients release];
	[super dealloc];
}

- (void)clearCache {
	@synchronized(self) {
		[files autorelease];
		files = nil;
	}
}

- (ZKQueryResult *)query:(NSString *)soql {
	ZKSforceClient *sforce = [clients checkout];
	@try {
		// NSLog(@"query: %@", soql);
		return [sforce query:soql];
	}
	@finally {
		[clients checkin:sforce];
	}
	return nil;
}

- (ZKQueryResult *)queryMore:(NSString *)locator {
	ZKSforceClient *sforce = [clients checkout];
	@try {
		return [sforce queryMore:locator];
	}
	@finally {
		[clients checkin:sforce];
	}
	return nil;
}

- (NSDictionary *)fetchFileList {
	ZKQueryResult *qr = [self query:[NSString stringWithFormat:@"select id, name, contentType, type, bodylength, createdDate, SystemModstamp from Document where Type != 'URL' and FolderId='%@'", sfdcId]];
	NSMutableDictionary *theFiles = [NSMutableDictionary dictionary];
	while (true) {
		for(ZKSObject *d in [qr records]) {
			File *nf = [[File alloc] initWithName:[d fieldValue:@"Name"] type:[d fieldValue:@"Type"] id:[d id] modstamp:[d dateTimeValue:@"SystemModstamp"] created:[d dateTimeValue:@"CreatedDate"] length:[d doubleValue:@"BodyLength"] folder:self];
			[theFiles setObject:nf forKey:[nf name]];
			[nf release];
		}
		if ([qr done]) break;
		qr = [self queryMore:[qr queryLocator]];
	}
	return theFiles;
}

- (NSDictionary *)files {
	@synchronized(self) {
		if ((files == nil) || ([NSDate timeIntervalSinceReferenceDate] > filesExpiry)) {
			[files release];
			files = [[self fetchFileList] retain];
			NSTimeInterval secondsTilExpiry = 60.0 * [[NSUserDefaults standardUserDefaults] integerForKey:P_DIR_CACHE_TIME];
			filesExpiry = [[NSDate dateWithTimeIntervalSinceNow:secondsTilExpiry] timeIntervalSinceReferenceDate];
		}
		return files;
	}
	return 0;
}

- (FileSystemItem *)fileWithName:(NSString *)docName {
	NSDictionary *contents = [self files];
	return [contents objectForKey:docName];
}

- (NSArray *)filenames {
	return [[self files] allKeys];
}

@end

@implementation RootFolder

- (NSDictionary *)fetchFileList {
	NSMutableDictionary *folders = [NSMutableDictionary dictionary];
	// fake 'folder' for the my personal documents virtual folder
	Folder *myDocs = [[[Folder alloc] initWithName:@"My Personal Documents" id:sfdcId modstamp:[NSDate date] created:[NSDate date] clientPool:clients] autorelease];
	[folders setObject:myDocs forKey:[myDocs name]];
	ZKQueryResult *qr = [self query:@"select id, name, CreatedDate, systemModstamp, isReadOnly from Folder where Type='Document'"];
	for(ZKSObject *f in [qr records]) {
		Folder *nf = [[Folder alloc] initWithName:[f fieldValue:@"Name"] id:[f id] modstamp:[f dateTimeValue:@"SystemModstamp"] created:[f dateTimeValue:@"CreatedDate"] clientPool:clients];
		[folders setObject:nf forKey:[nf name]];
		[nf release];
	}
	@try {
		qr = [self query:@"select id, name, createdDate, systemModstamp from ContentWorkspace"];
		for (ZKSObject *w in [qr records]) {
			Workspace *ws = [[Workspace alloc] initWithName:[w fieldValue:@"Name"] id:[w id] 
								modstamp:[w dateTimeValue:@"SystemModstamp"] created:[w dateTimeValue:@"CreatedDate"] clientPool:clients];
			[folders setObject:ws forKey:[ws name]];
			[ws release];
		}
		Folder *pws = [[[PersonalWorkspace alloc] initWithName:@"Personal Workspace" id:sfdcId modstamp:[NSDate date] created:[NSDate date] clientPool:clients] autorelease];
		[folders setObject:pws forKey:[pws name]];
	} @catch (ZKSoapException *ex) {
		// no access
	}
	return folders; 
}

@end

@implementation Workspace

- (NSDictionary *)fetchFileList {
	ZKQueryResult *qr = [self query:[NSString stringWithFormat:@"select contentDocument.title, contentDocumentId, contentDocument.latestPublishedVersionId, contentDocument.latestPublishedVersion.SystemmodStamp, contentDocument.latestPublishedVersion.CreatedDate, contentDocument.latestPublishedVersion.fileType, contentDocument.latestPublishedVersion.contentSize from contentWorkspaceDoc where contentWorkspaceId='%@'", sfdcId]];
	NSMutableDictionary *theFiles = [NSMutableDictionary dictionary];
	while (true) {
		for (ZKSObject *wd in [qr records]) {
			ZKSObject *doc = [wd fieldValue:@"ContentDocument"];
			ZKSObject *ver = [doc fieldValue:@"LatestPublishedVersion"];
			ContentFile *cf = [[ContentFile alloc] initWithName:[doc fieldValue:@"Title"]
											type:[ver fieldValue:@"FileType"] id:[doc fieldValue:@"LatestPublishedVersionId"] 
											modstamp:[ver dateTimeValue:@"SystemModstamp"]
											created:[ver dateTimeValue:@"CreatedDate"]
											length:[ver doubleValue:@"ContentSize"]
											folder:self];
			[theFiles setObject:cf forKey:[cf name]];
			[cf release];
		}
		if ([qr done]) break;
		qr = [self queryMore:[qr queryLocator]];
	}
	return theFiles;
}

@end


@implementation PersonalWorkspace

- (NSDictionary *)fetchFileList {
	ZKQueryResult *qr = [self query:@"select title, Id, latestPublishedVersionId, latestPublishedVersion.SystemmodStamp, latestPublishedVersion.CreatedDate, latestPublishedVersion.fileType, latestPublishedVersion.contentSize from contentDocument where PublishStatus='R'"];
	NSMutableDictionary *theFiles = [NSMutableDictionary dictionary];
	while (true) {
		for (ZKSObject *doc in [qr records]) {
			ZKSObject *ver = [doc fieldValue:@"LatestPublishedVersion"];
			ContentFile *cf = [[ContentFile alloc] initWithName:[doc fieldValue:@"Title"]
											type:[ver fieldValue:@"FileType"] id:[doc fieldValue:@"LatestPublishedVersionId"] 
											modstamp:[ver dateTimeValue:@"SystemModstamp"]
											created:[ver dateTimeValue:@"CreatedDate"]
											length:[ver doubleValue:@"ContentSize"]
											folder:self];
			[theFiles setObject:cf forKey:[cf name]];
			[cf release];
		}
		if ([qr done]) break;
		qr = [self queryMore:[qr queryLocator]];
	}
	return theFiles;
}

@end
